home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 / Ham Radio 2000.iso / ham2000 / packet / tf27bsrc / l2b.c < prev    next >
Text File  |  1995-05-23  |  46KB  |  884 lines

  1. /**************************************************************************\
  2. *                                                                          *
  3. *                                                                          *
  4. *    *****                      *****                                      *
  5. *      *****                  *****                                        *
  6. *        *****              *****                                          *
  7. *          *****          *****                                            *
  8. *            *****      *****                                              *
  9. *              *****  *****                                                *
  10. *            *****      *****                                              *
  11. *          *****          *****          The Firmware                      *
  12. *        *****              *****        Portable. Compatible.             *
  13. *      *****                  *****      Proteced by ALAS                  *
  14. *    *****                      *****    By NORD><LINK.                    *
  15. *                                                                          *
  16. *                                                                          *
  17. *                                                                          *
  18. *    L2B.C   -   Level 2, Teil 2                                           *
  19. *                                                                          *
  20. *    angelegt:      DC4OX                                                  *
  21. *    modifiziert:   DL8ZAW, 04.05.91                                       *
  22. *                   setiSRTT(): Anfangswert fuer SRTT setzen; ersetzt      *
  23. *                               setiT1().                                  *
  24. *                   inilbl():   IRTT mit Fpar initialisieren               *
  25. *                   sdipoll():  I-Frame als Poll aussenden (DK6PX)         *
  26. *                                                                          *
  27. *                   DL8ZAW, 31.05.91                                       *
  28. *                   setiSRTT(): Digipeateranzahl n ermitteln,              *
  29. *                               SRTT = (2*n+1) * IRTT                      *
  30. *                               (nur fuer Connect!)                        *
  31. *                   reslnk():   SRTT = IRTT setzen                         *
  32. *                                                                          *
  33. *                   DL8ZAW, 05.06.91                                       *
  34. *                   sdui(): Wenn UIPOLL definiert ist, UI-Frames mit       *
  35. *                           gesetzem POLL-Bit aussenden.                   *
  36. *                                                                          *
  37. *                   DL8ZAW, 19.06.91                                       *
  38. *                   itolnk(): nur compilieren, wenn FIRMWARE nicht         *
  39. *                             definiert ist, da diese Funktion in TF       *
  40. *                             NICHT benutzt wird!                          *
  41. *                                                                          *
  42. *                   clrlnk(): Wenn alle Links aufgeloest sind, dann        *
  43. *                             DAMA-Timer ruecksetzen                       *
  44. *                                                                          *
  45. *                   DK6PX, 20.07.91                                        *
  46. *                   sdi(): Je nach Laenge der I-Frames MAXFRAME erhoehen   *
  47. *                                                                          *
  48. *                   DB2OS, 29.08.91                                        *
  49. *                   digipt(): Zu "digipeatende" Frames trotz DAMA sofort   *
  50. *                             senden, auch wenn der eigene TNC nicht       *
  51. *                             gepollt wurde.                               *
  52. *                                                                          *
  53. *                   DB2OS, 03.09.91                                        *
  54. *                   sdi(): Timer T1 und RTT dürfen nur nach dem LETZTEN    *
  55. *                          zu sendenden I-Frame gestartet werden!!!        *
  56. *                          Nach dieser Modifikation funtioniert SRTT nun   *
  57. *                          richtig bzw. deutlich besser.                   *
  58. *                                                                          *
  59. *                   DB2OS, 17.09.91                                        *
  60. *                   sdui(): UIPOLL jetzt über Parameter @U gesteuert,      *
  61. *                           mittels Variable UIpar.                        *
  62. *                                                                          *
  63. *                   DL8ZAW, 27.03.92                                       *
  64. *                   tol3sw():  Weitergabe des Frames an L3 entfernt, weil  *
  65. *                              es in TheFirmware keinen L3 gibt.           *
  66. *                   itolnk():  entfernt, weil nicht benoetigt              *
  67. *                                                                          *
  68. *                   DB2OS, 21.6.93                                         *
  69. *                   sdi(): Dynam. Maxframe von DK6PX gestrichen, da        *
  70. *                          es damit besonders auf KW und schlechten        *
  71. *                          Links erhebliche Probleme gibt..                *
  72. *                                                                          *
  73. *                   DL4YBG, 23.10.93                                       *
  74. *                   setiSRTT(): An neue Strategie angepasst                *
  75. *                                                                          *
  76. *                   DG2FEF, 18.06.94                                       *
  77. *                   disc(): Bei DAMA kein DISC+ senden, sondern direkt auf *                                              *
  78. *                           Status DSCRQ.                                  *
  79. *                   l2stma(): Bei DAMA und State DSCRQ auf einem Link,     *
  80. *                             auf alle folgenden Frames mit DM- antworten  *
  81. *                             und auf State DSCED gehen. Nachricht ans     *
  82. *                             Terminal senden.                             *
  83. *                                                                          *
  84. *                   DG2FEF,18.07.94                                        *
  85. *                   disc(): Doch wieder DISC  senden, außer beim letzten   *
  86. *                           Link, um Deadlock bei DAMA zu verhindern       *         *
  87. *                   sdipoll(): Angepaßt für Aufruf aus der Statemachine    *
  88. *                   sdoi(): Angepaßt für Framesammler-Unterstützung        *
  89. *                   srxdNR(): dito                                         *
  90. *                   tol3sw(): entfernt.                                    *
  91. *                   dsclnk(): Code optimiert, ein paar Sachen aus Dcmd()   *
  92. *                             hier untergebracht.                          *
  93. *                   setiSRTT(): "initial SRTT" jetzt IRTT * (Digianzahl+1) *
  94. *                               nicht mehr IRTT * (Digianzahl*2+1)         *
  95. *                                                                          *
  96. *                   DG2FEF, 13.08.94                                       *
  97. *                   isnxti(): Framesammler nach OE1HHC/OE3GMW.             *
  98. *                                                                          *
  99. *                   DB2OS,  19.08.94                                       *
  100. *                   i2tolx(): noatou Timeout nicht benutzt und entfernt.   *
  101. *                                                                          *
  102. \**************************************************************************/
  103.  
  104.  
  105.  
  106.  
  107.  
  108. /*                                                             Includes   */
  109. /**************************************************************************/
  110.  
  111. #include "all.h"         /* allgemeine Festlegungen                       */
  112. #include "l2.h"          /* Festlegungen/Datenstrukturen fuer den Level 2 */
  113. #include "l2s.h"         /* Zugriff auf die State-Tabellen                */
  114. #include "l2ext.h"       /* globale Variable / nicht int-Funktionen       */
  115.  
  116.  
  117.  
  118.  
  119. /**************************************************************************\
  120. *                                                                          *
  121. * "new link"                                                               *
  122. *                                                                          *
  123. * Link (lnkpoi) neu aufbauen. Wenn Link noch nicht aktiv war, die Anzahl   *
  124. * aktiver Links (nmblks) erhoehen.                                         *
  125. *                                                                          *
  126. \**************************************************************************/
  127.  
  128. VOID newlnk()
  129.   {
  130.     reslnk();                           /* Sequenzvars/Timer ruecksetzen  */
  131.     setiSRTT();                         /* Anfangswert SRTT               */
  132.     txfV2 = YES;                        /* welche Protokollversion        */
  133.     xsabm();                            /* SABM senden                    */
  134.     if (lnkpoi->state == L2SDSCED)      /* neuer Link ?                   */
  135.       ++nmblks;                         /* ja ...                         */
  136.     lnkpoi->state = L2SLKSUP;           /* Linkstatus "Link Setup"        */
  137.   }
  138.  
  139.  
  140.  
  141.  
  142.  
  143. /**************************************************************************\
  144. *                                                                          *
  145. * "disconnect link"                                                        *
  146. *                                                                          *
  147. * Disconnect-Wunsch an aktuellen Link (lnkpoi) :                           *
  148. *                                                                          *
  149. *   Linkstatus "Disconnected"                                              *
  150. *   -> Ax.25-Parameter "frisch"                                            *
  151. *   FEF Gelöscht, passiert schon in Dcmd(), TFB.C                          *
  152. *                                                                          *
  153. *   Linkstatus "Link Setup" oder "Disconnect Request"                      *
  154. *   -> Link aufloesen, neuer Linkstatus "Disconnected"                     *
  155. *                                                                          *
  156. *   sonst                                                                  *
  157. *   -> Empfangsinfoframeliste loeschen, Linkstatus bleibt, Flag "nach      *
  158. *      Loswerden aller zu sendenden Infoframes disconnecten" setzen        *
  159. *                                                                          *
  160. \**************************************************************************/
  161.  
  162. VOID dsclnk()                                        /* FEF */
  163.   {
  164.     static unsigned lstate;
  165.  
  166.     if (   (lstate = lnkpoi->state) == L2SLKSUP
  167.         || lstate == L2SDSCRQ
  168.         || lnkpoi->flag & L2FDSLE
  169.        )
  170.       {
  171.         if (lnkpoi->flag & L2FDSLE)              /* Link aufzulösen?   */
  172.           disc();                                /* Dann los ...       */
  173.         else
  174.           {
  175.             if (lstate == L2SLKSUP)              /* Falls "Link setup" */
  176.               xdisc();                           /*    DISC senden.    */
  177.             mclrlk();                            /*    Link aufloesen  */
  178.             lnkpoi->state = L2SDSCED;            /*    Disconnected !  */
  179.           }
  180.       }
  181.     else
  182.       {                                              /* sonst           */
  183.         dealml(&lnkpoi->rcvdil);                     /* RX-Infoframe-   */
  184.         lnkpoi->rcvd = 0;                            /* loeschen und    */
  185.         dealml(&lnkpoi->collil);                     /* den Framesammler*/
  186.         lnkpoi->colled = 0;
  187.         lnkpoi->flag |= L2FDSLE;                     /* Flag, s.o.      */
  188.       }
  189.   }
  190.  
  191.  
  192.  
  193.  
  194.  
  195. /**************************************************************************\
  196. *                                                                          *
  197. * "digipeat"                                                               *
  198. *                                                                          *
  199. * Framebuffer, auf den fbp zeigt, abtesten, ob er ein zu digipeatendes     *
  200. * Paket enthaelt. Wenn ja, Paket an den entsprechenden Port (falls ein     *
  201. * bekannter Nachbarknoten direkt in der Digiliste folgt oder nach          *
  202. * kompletten Digipeaten das Ziel ist, kann das Paket auch auf einem        *
  203. * anderen als dem normalen HDLC-Port digipeatet werden) ausgeben.          *
  204. * Das Paket muss schon durch takfhd() analysiert sein, die rxf...-         *
  205. * Parameter muessen gesetzt sein.                                          *
  206. *                                                                          *
  207. * Return:  YES - das Frame wurde entweder digipeatet, oder der             *
  208. *                Framebuffer wurde deallokiert, weil das Frame noch von    *
  209. *                einer anderen Station digipeatet werden muss oder ich     *
  210. *                nicht digipeaten darf                                     *
  211. *          NO  - das Frame muss nicht mehr digipeated werden, hat alle     *
  212. *                noetigen Digipeater durchlaufen, ist zur Auswertung frei  *
  213. *                                                                          *
  214. * FEF Bei DAMA kein sendok = 1 mehr !!!                                    *
  215. *                                                                          *
  216. \**************************************************************************/
  217.  
  218. BOOLEAN digipt(fbp)
  219.  
  220. MBHEAD *fbp;
  221.  
  222.   {
  223.     static char       *viap;                      /* Zeiger in via-Liste  */
  224.     static unsigned    n;                         /* Zaehler              */
  225.  
  226.     viap = rxfhdr + L2ILEN;                       /* Anfang via-Liste     */
  227.     while (*viap != '\0')                         /* via-Liste durchgehen */
  228.       {
  229.         if (!(viap[L2IDLEN - 1] & L2CH))          /* zu digipeaten ?      */
  230.           {
  231.             if (Rpar == YES && istome(viap) == TRUE)   /* ja, darf ich    */
  232.               {                                        /* und muss ich :  */
  233.                 rwndmb(fbp);                           /* Zeiger auf Hbit */
  234.                 n = (unsigned)(viap - (rxfhdr+L2ILEN) + (L2ILEN+L2IDLEN));
  235.                 while (n-- != 0) getchr(fbp);          /* berechnen       */
  236.                 *(fbp->mbbp - 1) |= L2CH;              /* Hbit setzen     */
  237.                 viap += L2IDLEN;                       /* Nachbardigi     */
  238.                 fbp->l2port = nbrprt(   *viap != '\0'  /* ich letzter ?   */
  239.                                       ? viap           /* nein, Port Digi */
  240.                                       : rxfhdr);       /* ja, Port Ziel   */
  241.                 fbp->l2fflg = 0;                       /* kein Linkframe  */
  242.                 sdl2fr(fbp);                           /* Frame senden <-+*/
  243.               }
  244.             else              /* Frame ist noch nicht komplett digipeatet */
  245.               dealmb(fbp);    /* und/oder nix fuer mich, Frame wegwerfen  */
  246.             return (YES);     /* fuer aufrufende Funk.: Frame ist weg !   */
  247.           }
  248.         viap += L2IDLEN;      /* naechsten Digi in Digiliste untersuchen  */
  249.       }
  250.     return (NO);              /* fuer aufrufende Funk.: Frame auswerten ! */
  251.   }
  252.  
  253.  
  254.  
  255. /**************************************************************************\
  256. *                                                                          *
  257. * "level 2 information to level x"                                         *
  258. *                                                                          *
  259. * Infopakete aus dem aktuellen Link (lnkpoi) an hoehere Level weiter-      *
  260. * reichen. nocgnc gibt an, ob der hoehere Level die "Erstickungskontrolle" *
  261. * (hier = Beruecksichtigung der maximal noch anzunehmenden I-Pakete)       *
  262. * machen soll (NO) oder in jedem Fall alle uebermittelten I-Pakete         *
  263. * annehmen muss (YES). Falls die I-Pakete vom hoeheren Level angenommen    *
  264. * wurden, Empfangszaehler rcvd entsprechend hochzählen.                    *
  265. * Es wird l2link in den Framekoepfen der weitergereichten Pakete           *
  266. * auf lnkpoi gesetzt und type auf 2 fuer "Level 2".                        *
  267. *                                                                          *
  268. \**************************************************************************/
  269. VOID i2tolx(nocgnc)
  270.  
  271. unsigned nocgnc;
  272.  
  273.   {
  274.     static MBHEAD *rcvdip;   /* Zeiger auf Framekopf weiterzureichendes I */
  275.  
  276.     while (lnkpoi->rcvd != 0)           /* solange I's aus Link vorhanden */
  277.       {
  278.         (rcvdip = lnkpoi->rcvdil.head)->l2link = lnkpoi;    /* Linkzeiger */
  279.         rcvdip->type = 2;                                   /* Level 2 !  */
  280.         if (!fmlink(nocgnc,rcvdip))     /* I an hoeheren Level geben      */
  281.           return;                       /* Abbruch, wenn nicht angenommen */
  282.         --lnkpoi->rcvd;                 /* Empfangspaketezaehler updaten  */
  283.       }
  284.   }
  285.  
  286.  
  287.  
  288.  
  289.  
  290. /**************************************************************************\
  291. *                                                                          *
  292. * "serve received N(R)"                                                    *
  293. *                                                                          *
  294. * Aktuell empfangenes N(R) (rxfctl) des aktuellen Links (lnkpoi) auswerten *
  295. * und entsprechend verfahren (s.u.).                                       *
  296. *                                                                          *
  297. * Return:  YES - aktuell empfangenes N(R) ist okay oder Linkzustand        *
  298. *                laesst N(R)-Empfang nicht zu                              *
  299. *          NO  - aktuell empfangenes N(R) ist falsch                       *
  300. *                                                                          *
  301. \**************************************************************************/
  302.  
  303. BOOLEAN srxdNR()
  304.   {
  305.     static unsigned rxdNR;   /* empfangenes N(R)                          */
  306.     static unsigned newok;   /* Anzahl neu bestaetigte I's                */
  307.     static unsigned outstd;  /* Anzahl ausstehende (nicht bestaetigte) I's*/
  308.     static unsigned l2state; /* Linkstatus des aktuellen Links            */
  309.  
  310.     if ((l2state = lnkpoi->state) >= L2SIXFER)    /* darf N(R) kommen ?   */
  311.       {
  312.         if (    ( outstd = (lnkpoi->VS - lnkpoi->lrxdNR) & 0x07
  313.                 ) != 0
  314.              && ( newok = ( (rxdNR = (rxfctl >> 5) & 0x07) - lnkpoi->lrxdNR
  315.                           ) & 0x07
  316.                 ) != 0             /* N(R) nur auswerten, wenn I's aus-   */
  317.            )                       /* stehen und neue bestaetigt werden   */
  318.           if (newok <= outstd)     /* N(R) okay ?                         */
  319.             {
  320.               if (((lnkpoi->RTTNR - lnkpoi->lrxdNR) & 0x07) >= newok)
  321.                 clrRTT();                      /* FEF RTT-Messung stoppen */
  322.               lnkpoi->lrxdNR = rxdNR;   /* ja, N(R) annehmen              */
  323.               clrT1();                  /* T1 stoppen                     */
  324.               if (newok != outstd)      /* wenn immer noch I's ausstehend */
  325.                 if (lnkpoi->flag & L2FMAXF1)     /* Retryen wir ?         */
  326.                   lnkpoi->VS = rxdNR;            /* V(S) resetten         */
  327.                 else
  328.                   setT1();              /* T1 neu starten                 */
  329.               else
  330.                 lnkpoi->flag &= ~L2FMAXF1;     /* FEF alles bestätigt ... */
  331.  
  332.               while (newok-- != 0)
  333.                 {                                      /* alle neu        */
  334.       dealmb(unlink(lnkpoi->sendil.head));  /* bestaetigten    */
  335.                   --lnkpoi->tosend;                    /* I's wegwerfen   */
  336.                 }
  337.             }
  338.           else
  339.             {                           /* nein,                          */
  340.               sdfrmr(0x08);             /* Kontrollfeld hat falsches N(R) */
  341.               return (FALSE);           /* N(R) nicht okay !              */
  342.             }
  343.  
  344.           if (!rxfCR && rxfPF != 0)          /* wenn empfangenes Frame    */
  345.             {                                /* Response mit Final war,   */
  346.               clrT1();                       /* Timer 1 stoppen und       */
  347.               lnkpoi->RTT = 0;               /* FEF RTT wieder zulassen   */
  348.               lnkpoi->flag &= ~L2FDIRTY;
  349.               lnkpoi->VS = lnkpoi->lrxdNR;   /* V(S) updaten              */
  350.             }
  351.           else
  352.             if (   l2state == L2SWA          /* FEF umgestellt wegen RNR- */
  353.                 || l2state == L2SWADBS       /* recovery                  */
  354.                 || l2state == L2SWARBS
  355.                 || l2state == L2SWABBS
  356.                )
  357.               if (!lnkpoi->T1) setT1();
  358.       }
  359.  
  360.     return (TRUE);                      /* N(R) okay oder nicht benutzt   */
  361.   }
  362.  
  363.  
  364.  
  365.  
  366.  
  367. /**************************************************************************\
  368. *                                                                          *
  369. * "is next I"                                                              *
  370. *                                                                          *
  371. * Testen, ob das aktuell empfangene I-Frame (rxf...) das naechste fuer den *
  372. * aktuellen Linkblock (lnkpoi) erwartete I-Frame ist, wenn der Linkzustand *
  373. * Informationstransfer zulaesst. Bei nicht erwarteter Sequenznummer        *
  374. * entsprechende Statetable abarbeiten.                                     *
  375. *                                                                          *
  376. * Return :  YES - I-Frame ist das naechste erwartete oder Linkzustand      *
  377. *                 laesst keinen Informationstransfer zu                    *
  378. *           NO  - sonst                                                    *
  379. * DG2FEF:                                                                  *
  380. * Umgebaut für Framesammler.                                               *
  381. *                                                                          *
  382. * Return nun:   0 - I-Frame ist falsch, nicht zu gebrauchen für Frame-     *
  383. *                   sammler, also verwerfen                                *
  384. *               1 - I-Frame ist OK, in normale Linkliste einhängen, bzw.   *
  385. *                   Linkzustand erlaubt keinen I-Transfer                  *
  386. *               2 - I-Frame ist falsch, kann aber in den Framesammler      *
  387. *                                                                          *
  388. *                                                                          *
  389. \**************************************************************************/
  390.  
  391. unsigned isnxti()
  392.   {
  393.     static unsigned iseqno;                       /* I Sequence Number    */
  394.  
  395.     if (lnkpoi->state >= L2SIXFER)                        /* I-Transfer ? */
  396.       if ((iseqno = (rxfctl >> 1) & 0x07) == lnkpoi->VR)  /* I erwartet ? */
  397.         if (((lnkpoi->ltxdNR + 7) & 0x07) != iseqno)      /* kein Ueber-  */
  398.           {                                               /* lauf ?       */
  399.             if (nmbfre > L2BREMSE)                        /* noch Platz?  */
  400.               lnkpoi->VR = (iseqno + 1) & 0x07;           /* V(R) setzen  */
  401.           }
  402.         else
  403.           {
  404.             sdfrmr(0x01);      /* Kontrollfeld falsch/nicht implementiert */
  405.             return (0);
  406.           }
  407.       else                                       /* unerwartetes I (nicht */
  408.         {                                        /* naechstes in Reihe)   */
  409.           l2stma(!rxfPF ? stbl26 : stb26b);      /* INVALID N(S) RECEIVED */
  410.  
  411.           if (!lnkpoi->colled)                   /* Framesammler noch aus */
  412.             {                                    /* nur 1 Frame verloren? */
  413.               if (   iseqno == ((lnkpoi->VR+1) & 0x07)
  414.                   && iseqno != lnkpoi->xpctVR)
  415.                 {
  416.                   ++lnkpoi->colled;              /* dann Framesammler ein */
  417.                   lnkpoi->xpctVR = lnkpoi->VR;
  418.                 }
  419.             }
  420.           else                                   /* schon ein Frame drin  */
  421.             if (iseqno == lnkpoi->lastVR)        /* paßt an das letzt im  */
  422.               ++lnkpoi->colled;                  /* Sammler, also rein    */
  423.             else                                 /* sonst:                */
  424.               return(0);                         /* weg damit!            */
  425.  
  426.           if (lnkpoi->colled)               /* Sammler ist ein, Frame ok  */
  427.             {
  428.               lnkpoi->lastVR = (iseqno+1) & 0x07;  /* V(R) merken */
  429.               return(2);                       /* Frame in Sammler, bitte */
  430.             }
  431.  
  432.           return (0);                            /* unerwartetes I !      */
  433.         }
  434.  
  435.     return (1);          /* I richtig oder Linkzustand ohne I-Transfer    */
  436.   }
  437.  
  438.  
  439.  
  440.  
  441.  
  442. /**************************************************************************\
  443. *                                                                          *
  444. * "initialize link"                                                        *
  445. *                                                                          *
  446. * Aktuellen Linkblock (lnkpoi) initialisieren. Sequenzvariablen und Timer  *
  447. * initialisieren, Quellcall/Zielcall/via-Liste/ Port setzen aus der        *
  448. * txf...-Liste.                                                            *
  449. *                                                                          *
  450. \**************************************************************************/
  451.  
  452. VOID inilnk()
  453.   {
  454.     reslnk();                                /* Sequenzvars/Timer init.   */
  455.     cpyid(lnkpoi->srcid,txfhdr + L2IDLEN);   /* Quellcall                 */
  456.     cpyid(lnkpoi->dstid,txfhdr);             /* Zielcall                  */
  457.     cpyidl(lnkpoi->viaidl,txfhdr + L2ILEN);  /* via-Liste                 */
  458.     lnkpoi->liport = txfprt;                 /* Port                      */
  459.   }
  460.  
  461.  
  462.  
  463.  
  464.  
  465. /**************************************************************************\
  466. *                                                                          *
  467. * "set initial SRTT"                                                       *
  468. * FEF                                                                      *
  469. * Anfangswert fuer Smoothed Round Trip Timer setzen                        *
  470. *                                                                          *
  471. \**************************************************************************/
  472.  
  473. VOID setiSRTT()
  474.   {
  475.     char       *viap;                   /* Zeiger in via-Liste            */
  476.     unsigned    n;                      /* Digizaehler                    */
  477.  
  478.     viap = lnkpoi->viaidl;              /* Anfang via-Liste               */
  479.     n = 0;                              /* noch kein Digi gezaehlt        */
  480.     while (*viap != '\0')               /* Digianzahl ermitteln           */
  481.       {
  482.         ++n;
  483.         viap += L2IDLEN;
  484.       }
  485.     ++n;                                      /* FEF  Digianzahl + 1      */
  486.  
  487.     lnkpoi->SRTT = n * lnkpoi->IRTT;
  488.     lnkpoi->IT1 = A3par * lnkpoi->SRTT; /* initial T1-timerwert */
  489.     lnkpoi->RTT = 0;
  490.    /* ende */
  491.   }
  492.  
  493.  
  494.  
  495.  
  496.  
  497. /**************************************************************************\
  498. *                                                                          *
  499. * "messaged clear link"                                                    *
  500. *                                                                          *
  501. * Aktuellen Link aufloesen (siehe clrlnk()) und entsprechende Meldung an   *
  502. * hoehere Level geben ("Disconnected from").                               *
  503. *                                                                          *
  504. \**************************************************************************/
  505.  
  506. VOID mclrlk()
  507.   {
  508.     l2tolx(L2MDISCF);                   /* und hoehere Level informieren  */
  509.     clrlnk();                           /* Link aufloesen                 */
  510.   }
  511.  
  512.  
  513.  
  514.  
  515.  
  516. /**************************************************************************\
  517. *                                                                          *
  518. * "clear link"                                                             *
  519. *                                                                          *
  520. * Aktuellen Link (lnkpoi) aufloesen. Alle Sequenzvariablen und Timer       *
  521. * zuruecksetzen, Sende- und Empfangsinfoframelise loeschen, Linkblock neu  *
  522. * mit AX.25-Parametern besetzen, Anzahl der aktiven Links (nmblks) um 1    *
  523. * erniedrigen.                                                             *
  524. *                                                                          *
  525. \**************************************************************************/
  526.  
  527. VOID clrlnk()
  528.   {
  529.     reslnk();                           /* Sequenzvars/Timer ruecksetzen  */
  530.     dealml(&lnkpoi->rcvdil);            /* Empfangsinfoliste loeschen     */
  531.     dealml(&lnkpoi->sendil);            /* Sendeinfoliste loeschen        */
  532.     dealml(&lnkpoi->collil);            /* FEF Framesammler löschen       */
  533.     --nmblks;                           /* nun ein aktiver Link weniger   */
  534.     lnkpoi->colled =
  535.     lnkpoi->rcvd = lnkpoi->tosend = 0;  /* entsprechende Zaehler loeschen */
  536.     inilbl();                           /* Linkblock "frisch"             */
  537.   }
  538.  
  539.  
  540.  
  541.  
  542.  
  543. /**************************************************************************\
  544. *                                                                          *
  545. * "disconnect"                                                             *
  546. * FEF                                                                      *
  547. * Disconnect des aktuellen Links (lnkpoi) einleiten. Alle Sequenzvariablen *
  548. * und Timer zuruecksetzen, DISC senden, neuer Status "Disconnect request". *
  549. *                                                                          *
  550. \**************************************************************************/
  551.  
  552. VOID disc()
  553.   {
  554.     if (damaok)
  555.      {
  556.       if (aktlks > 1)                    /* mehr als 1 QSO mit dem Master */
  557.         {
  558.           xdisc();
  559.           reslnk();
  560.           lnkpoi->state = L2SDSCRQ;
  561.         }
  562.       else                                 /* aktlks <= 1 */
  563.         if (nmblks == 1)                   /* letztes QSO mit DAMA-Master */
  564.           {
  565.            reslnk();
  566.            lnkpoi->state = L2SDSCRQ;
  567.           }
  568.      }
  569.     else
  570.      {
  571.        xdisc();
  572.        reslnk();
  573.        lnkpoi->state = L2SDSCRQ;
  574.      }
  575.   }
  576.  
  577.  
  578.  
  579.  
  580. /**************************************************************************\
  581. *                                                                          *
  582. * "reset link"                                                             *
  583. *                                                                          *
  584. * Aktuellen Link (lnkpoi) zuruecksetzen. Alle Sequenzvariablen und Timer   *
  585. * initialisieren.                                                          *
  586. *                                                                          *
  587. \**************************************************************************/
  588.  
  589. VOID reslnk()
  590.   {
  591.        lnkpoi->VS
  592.      = lnkpoi->RTT      /* FEF */
  593.      = lnkpoi->VR
  594.      = lnkpoi->ltxdNR
  595.      = lnkpoi->lrxdNR
  596.      = lnkpoi->flag
  597.      = 0;
  598.      lnkpoi->xpctVR = 8;   /* FEF */
  599.      lnkpoi->SRTT = lnkpoi->IRTT;
  600.      clrT1();
  601.      clrT2();
  602.   }
  603.  
  604.  
  605.  
  606.  
  607.  
  608. /**************************************************************************\
  609. *                                                                          *
  610. * "initialize link block"                                                  *
  611. *                                                                          *
  612. * Aktuellen Linkblock (lnkpoi) mit AX.25-Parametern initialisieren.        *
  613. * Loeschen des Quellrufzeichens, Setzen von FRACK, MAXFRAME, RETRY.        *
  614. *                                                                          *
  615. \**************************************************************************/
  616.  
  617. VOID inilbl()
  618.   {
  619.     cpyid(lnkpoi->srcid,myid); /* FEF Quellcall des Linkblocks auf myid[] */
  620.     lnkpoi->IRTT    = Fpar;
  621.     lnkpoi->k       = Opar;
  622.     lnkpoi->N2      = Npar;
  623.   }
  624.  
  625.  
  626.  
  627.  
  628.  
  629. /**************************************************************************\
  630. * [DG2FEF]                                                                 *        *
  631. * "send one outstanding I"                                                 *                     *
  632. * Aus dem Aktuellen Linkblock wird ein Frame gesendet. Der alte Zähler-    *
  633. * stand V(S) wird gerettet und anschließend wieder hergestellt             *
  634. *                                                                          *
  635. \**************************************************************************/
  636.  
  637. VOID sdoi()
  638.   {
  639.    lnkpoi->RTT = 0;
  640.    if (lnkpoi->VS != lnkpoi->lrxdNR)
  641.     {
  642.      lnkpoi->flag |= L2FMAXF1;                      /* MaxFrame 1 !    */
  643.      lnkpoi->oldVS = lnkpoi->VS;                    /* FEF V(S) retten */
  644.      lnkpoi->VS = lnkpoi->lrxdNR;                   /* V(S) resetten   */
  645.      sdi(1);                                        /* 1 I senden      */
  646.      lnkpoi->VS = lnkpoi->oldVS;         /* FEF V(S) wieder herstellen */
  647.     }
  648.   }
  649.  
  650.  
  651.  
  652.  
  653.  
  654. /**************************************************************************\
  655. *                                                                          *
  656. * "send I"                                                                 *
  657. *                                                                          *
  658. * Aus dem aktuellen Linkblock (lnkpoi) maximal max I-Frames aus der        *
  659. * Infomessageliste aufbauen und senden. Infos ueber 256 Bytes werden       *
  660. * gesplittet und dann gesendet. Die Frames werden als Commandframes ohne   *
  661. * Poll/Final-Bit gesendet. V(S) wird fuer jedes gesendete Frame erhoeht    *
  662. * modulo 7. Timer 2 und Timer 3 werden abgeschaltet.                       *
  663. *                                                                          *
  664. \**************************************************************************/
  665.  
  666. VOID sdi(max)
  667.  
  668. unsigned max;
  669.  
  670.   {
  671.     static unsigned    n, k;                 /* Zaehler zu sendende Infos */
  672.     static MBHEAD     *sendip;               /* Kopfzeiger Infobuffer     */
  673.     static MBHEAD     *fbp;                  /* Kopfzeiger Framebuffer    */
  674.  
  675.     for ( n = 0, sendip = lnkpoi->sendil.head;    /* maximal max I-Frames */
  676.           n < lnkpoi->tosend && n < max;          /* aus der Linkblock-   */
  677.           ++n, sendip = sendip->nextmh            /* infoliste senden     */
  678.         )                                         /* wenn vorhanden       */
  679.       {
  680.         stxfad();                            /* Frameadresse aufbauen     */
  681.         txfV2 = YES;                         /* Version                   */
  682.         txfCR = L2CCR;                       /* Command !                 */
  683.         txfPF = 0;                           /* kein Poll/Final           */
  684.         txfctl = setNR(lnkpoi->VS << 1);     /* Controlbyte I setzen      */
  685.         ++lnkpoi->VS;                        /* V(S) erhoehen             */
  686.         lnkpoi->VS &= 0x07;                  /* modulo 7                  */
  687.  
  688.         if (n == max-1 || n == lnkpoi->tosend-1)   /* letzter Info-Frame? */
  689.          {
  690.           fbp = makfhd(L2FT1ST|L2FRTTST);    /* Ja, T1 und RTT-Messung an */
  691.           if (!lnkpoi->RTT)                  /* FEF wenn keine Messung    */
  692.             lnkpoi->RTTNR = lnkpoi->VS;      /* FEF VS für RTT merken     */
  693.          }
  694.         else
  695.           fbp = makfhd(0x00);                /* Nein, T1/RTT nicht starten!*/
  696.  
  697.         putchr(sendip->l2fflg, fbp);         /* Frame aufbauen, PID       */
  698.         if (splcpy(256,fbp,sendip) == YES)   /* Message hineinkopieren    */
  699.           ++lnkpoi->tosend;                  /* falls Split eine mehr     */
  700.         sdl2fr(fbp);                         /* Frame senden              */
  701.         if (!sendok)                         /* FEF noch nicht gepollt?   */
  702.           lnkpoi->flag |= L2FJSENT;          /* FEF Frames in TX-Liste    */
  703.         clrT2();                             /* Timer 2 abschalten        */
  704.         clrT3();                             /* Timer 3 abschalten        */
  705.       }
  706.   }
  707.  
  708.  
  709.  
  710. /**************************************************************************\
  711. *                                                                          *
  712. * "send I with POLL-Bit"  (DK6PX)                                          *
  713. * FEF                                                                      *
  714. * Ein I-Frame aus Infomessageliste aufbauen, POLL-Bit setzen und senden.   *
  715. *                                                                          *
  716. \**************************************************************************/
  717.  
  718. VOID sdipoll()
  719.  {
  720.     static MBHEAD     *sendip;               /* Kopfzeiger Infobuffer     */
  721.     static MBHEAD     *fbp;                  /* Kopfzeiger Framebuffer    */
  722.  
  723.     sendip = (MBHEAD *)lnkpoi->sendil.head;
  724.     stxfad();                                /* Frameadresse aufbauen     */
  725.     if (   sendip->mbpc < Ipar               /* FEF wird's ein IPoll ?    */
  726.         && lnkpoi->tries < 3
  727.         && lnkpoi->tosend)
  728.      {
  729.       txfV2 = YES;                           /* Version                   */
  730.       txfCR = L2CCR;                         /* Command !                 */
  731.       txfPF = L2CPF;                         /* Poll/Final !              */
  732.       txfctl = setNR(lnkpoi->lrxdNR << 1);   /* Controlbyte I wie zuvor   */
  733.       putchr(sendip->l2fflg,                 /* Frame aufbauen, PID       */
  734.              fbp = makfhd(L2FT1ST));
  735.       splcpy(256,fbp,sendip);                /* Message umkopieren        */
  736.       sdl2fr(fbp);                           /* Frame senden              */
  737.       clrT2();                               /* Timer 2 abschalten        */
  738.       clrT3();                               /* Timer 3 abschalten        */
  739.      }
  740.     else                                     /* FEF Nein, kein Ipoll...   */
  741.       xrrc();                                /* FEF ... RR+ senden        */
  742.  }
  743.  
  744.  
  745. /**************************************************************************\
  746. *                                                                          *
  747. * "split copy"                                                             *
  748. *                                                                          *
  749. * Die Bytes aus dem Messagebuffer, auf dessen Kopf mbhd zeigt, in den      *
  750. * Framebuffer, auf dessen Kopf fbp zeigt, kopieren. Es werden hoechstens   *
  751. * max Bytes kopiert, hat die Message mehr Bytes, so wird ein neuer         *
  752. * Messagebuffer angelegt, die restlichen Messagebytes werden in diesen     *
  753. * Buffer kopiert, der neue Buffer wird hinter den alten Messagebuffer      *
  754. * gehaengt, der Putcount des alten Buffers wird auf max gestellt, das      *
  755. * "more follows"-Flag morflg des neuen Buffers wird geloescht, l2fflg wird *
  756. * uebertragen.                                                             *
  757. *                                                                          *
  758. * Return :  YES - der Messagebuffer wurde aufgesplittet                    *
  759. *           NO  - sonst                                                    *
  760. *                                                                          *
  761. \**************************************************************************/
  762.  
  763. BOOLEAN splcpy(max,fbp,mbhd)
  764.  
  765. unsigned    max;
  766. MBHEAD     *fbp;
  767. MBHEAD     *mbhd;
  768.  
  769.   {
  770.     char       *mbbpsa;                 /* Sicherung mbbp                 */
  771.     BOOLEAN     split;                  /* TRUE: Split erfolgt            */
  772.     unsigned    mbgcsa;                 /* Sicherung mbgc                 */
  773.     unsigned    mbgc2;                  /* mbgc alt -> mbpc alt           */
  774.     unsigned    n;                      /* Zaehler                        */
  775.     MBHEAD     *mbhd2;                  /* Kopfzeiger neuer Messagebuffer */
  776.  
  777.     split = NO;                         /* zunaechst nichts gesplittet    */
  778.     mbbpsa = mbhd->mbbp;                /* Bufferpointer sichern          */
  779.     mbgcsa = mbhd->mbgc;                /* Getcounter sichern             */
  780.     for (n = 0; mbhd->mbgc < mbhd->mbpc && n < max; ++n)
  781.       putchr(getchr(mbhd),fbp);         /* maximal max Bytes kopieren     */
  782.     if (mbhd->mbgc < mbhd->mbpc)        /* noch Bytes ueber -> Split !    */
  783.       {
  784.         mbgc2 = mbhd->mbgc;             /* Getcount fuer spaeter merken   */
  785.         mbhd2 = allocb();               /* neuen Buffer erzeugen          */
  786.         while (mbhd->mbgc < mbhd->mbpc) /* die restlichen Bytes in diesen */
  787.           putchr(getchr(mbhd),mbhd2);   /* Buffer kopieren                */
  788.         rwndmb(mbhd2);                  /* neuen Buffer rewinden          */
  789.         mbhd2->morflg = NO;             /* noch dem neuen folgt keiner    */
  790.         mbhd2->l2fflg = mbhd->l2fflg;   /* Frameflag uebertragen          */
  791.         relink(mbhd2,mbhd);             /* neu. Buf. hinter alten haengen */
  792.         mbhd->mbpc = mbgc2;             /* alter Buffer nur max Zeichen ! */
  793.         split = YES;                    /* wir mussten splitten           */
  794.       }
  795.     mbhd->mbbp = mbbpsa;                /* Bufferpointer restaurieren     */
  796.     mbhd->mbgc = mbgcsa;                /* Getcount restaurieren          */
  797.     return (split);                     /* Split oder nicht               */
  798.   }
  799.  
  800.  
  801.  
  802.  
  803.  
  804. /**************************************************************************\
  805. *                                                                          *
  806. * "send UI"                                                                *
  807. *                                                                          *
  808. * UI-Frame aufbauen und senden. Das UI-Frame wird an ID dest geschickt     *
  809. * ueber den Port port und die via-Liste (nullterminiert) vial, als Quelle  *
  810. * wird source genommen, die Infobytes des Frames stehen im Messagebuffer,  *
  811. * auf dessen Kopf mbhd zeigt, die PID wird aus l2fflg dieses Buffers       *
  812. * genommen.                                                                *
  813. *                                                                          *
  814. \**************************************************************************/
  815.  
  816. VOID sdui(vial,dest,source,port,mbhd)
  817.  
  818. char     *vial;
  819. char     *dest;
  820. char     *source;
  821. unsigned  port;
  822. MBHEAD   *mbhd;
  823.  
  824.   {
  825.     MBHEAD        *fbp;                           /* Zeiger auf Framekopf */
  826.  
  827.     cpyid(txfhdr + L2IDLEN,source);               /* Quelle setzen        */
  828.     cpyid(txfhdr,dest);                           /* Ziel setzen          */
  829.     cpyidl(txfhdr + L2ILEN,vial);                 /* via-Liste setzen     */
  830.     txfprt = port;                                /* Port setzen          */
  831.     txfV2 = YES;                                  /* Protokollversion     */
  832.     txfCR = L2CCR;                                /* Command !            */
  833.     if(UIpar)
  834.       txfPF = L2CPF;                              /* Poll-Bit gesetzt!    */
  835.     else
  836.       txfPF = 0;                                  /* kein Poll/Final      */
  837.     txfctl = L2CUI;                               /* UI-Frame !           */
  838.     putchr(mbhd->l2fflg,fbp = makfhd(0));         /* Frame aufbauen, PID  */
  839.     while (mbhd->mbgc < mbhd->mbpc)               /* Message -> Frame     */
  840.       putchr(getchr(mbhd),fbp);
  841.     sdl2fr(fbp);                                  /* Frame senden         */
  842.   }
  843.  
  844.  
  845.  
  846.  
  847.  
  848. /**************************************************************************\
  849. *                                                                          *
  850. * "level 2 state machine"                                                  *
  851. *                                                                          *
  852. * Ausfuehren der Zustandsuebergangsfunktion des Linkstatus (state) des     *
  853. * aktuellen Linkblocks (lnkpoi) in der Statetable stbl, danach einnehmen   *
  854. * des durch die Statetable gegebenen neuen Zustands.                       *
  855. *                                                                          *
  856. * In der Protokollversion 1 (dort gibt es nur 5 Zustaende), alle Zustaende *
  857. * oberhalb Informationstransfer auf Informationstransfer setzen.           *
  858. *                                                                          *
  859. *                                                                          *
  860. \**************************************************************************/
  861.  
  862. VOID l2stma(stbl)
  863.  
  864. STENTRY stbl[];
  865.  
  866.   {                                                     /* FEF */
  867.     if (   (lnkpoi->flag & L2FPOLL)               /* wenn gepollt ...     */
  868.         && lnkpoi->state == L2SDSCRQ)             /* und State DSCRQ      */
  869.       {                                           /* State 3 nach 0       */
  870.        xdm();                                     /* DM- senden           */
  871.        lnkpoi->state = L2SDSCED;                  /* State DISCED         */
  872.        mclrlk();                                  /* auflösen/melden      */
  873.       }
  874.     else
  875.       {
  876.        (*stbl[lnkpoi->state].func)();                 /* Funktion     */
  877.        lnkpoi->state = stbl[lnkpoi->state].newstate;  /* neuer Status */
  878.       }
  879.   }
  880.  
  881.  
  882.  
  883. /* Ende von L2B.C */
  884.